package com.sd365.permission.centre.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.sd365.common.core.common.aop.MyPageInfo;
import com.sd365.common.core.context.BaseContextHolder;
import com.sd365.common.util.BeanUtil;
import com.sd365.permission.centre.dao.mapper.*;
import com.sd365.permission.centre.entity.*;
import com.sd365.permission.centre.pojo.dto.*;
import com.sd365.permission.centre.pojo.query.UserOnlineQuery;
import com.sd365.permission.centre.service.UserOnlineService;
import com.sd365.permission.centre.service.config.websocket.WebSocketMessage;
import com.sd365.permission.centre.service.config.websocket.WebSocketServer;
import com.sd365.permission.centre.service.util.HttpUtils;
import com.sd365.permission.centre.service.util.ServletUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @Description: 用户在线管理服务
 * @Author: WengYu
 * @CreateTime: 2022/06/22 16:53
 */
@Service
@Slf4j
public class UserOnlineServiceImpl implements UserOnlineService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private DepartmentMapper departmentMapper;

    @Autowired
    private TenantMapper tenantMapper;

    @Autowired
    private PositionMapper positionMapper;

    @Autowired
    private CompanyMapper companyMapper;

    @Autowired
    private OrganizationMapper organizationMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    private static final String USER_LOGING_KEY = "user:loginInfo:";
    private static final String USER_TOKEN_KEY = "user:token:";

    @Override
    public List<UserOnlineDTO> getOnlineUsers(UserOnlineQuery userOnlineQuery) {
        // 获取所有已登陆的用户
        List<User> userList = this.searchLoginUsers(userOnlineQuery);
        List<UserOnlineDTO> userOnlineDTOS = new ArrayList<>();
        // 查询在线用户 用户状态为3 并且redis中存在代表在线
        for (User user : userList) {
            Object o = redisTemplate.opsForValue().get(USER_LOGING_KEY + user.getId());
            UserOnlineDTO userOnlineDTO = (UserOnlineDTO) o;
            if (this.selectOnlineByInfo(userOnlineQuery, userOnlineDTO)) {
                userOnlineDTOS.add(userOnlineDTO);
            }
        }
        Page page = (Page) userList;
        BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo(page.getTotal(), page.getPages())));
        return userOnlineDTOS;
    }

    private List<User> searchLoginUsers(UserOnlineQuery userOnlineQuery) {
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria().andEqualTo("status", 3);
        if (!StringUtils.isEmpty(userOnlineQuery.getCode()) && !StringUtils.isEmpty(userOnlineQuery.getName())) {
            criteria.andLike("code", "%" + userOnlineQuery.getCode() + "%")
                    .andLike("name", "%" + userOnlineQuery.getName() + "%");

        } else if (!StringUtils.isEmpty(userOnlineQuery.getCode())) {
            criteria.andLike("code", "%" + userOnlineQuery.getCode() + "%");

        } else if (!StringUtils.isEmpty(userOnlineQuery.getName())) {
            criteria.andLike("name", "%" + userOnlineQuery.getName() + "%");
        }
        return userMapper.selectByExample(example);
    }

    @Override
    public void forceLogout(String ids) {
        if (!StringUtils.isEmpty(ids)) {
            String[] split = ids.split(",");
            for (String id : split) {
                log.info("当前操作id{}", id);
                userMapper.updateUserOnlineStatus(Long.parseLong(id), (byte) 1);
                redisTemplate.delete(USER_LOGING_KEY + id);
                redisTemplate.delete(USER_TOKEN_KEY + id);
                WebSocketServer.close(JSON.toJSONString(new WebSocketMessage(0, "您的登陆状态发生变化，请重新登录!")), id);
            }
        }
    }

    @Override
    public void saveLoginInfo(User user) {
        UserOnlineDTO userOnlineDTO = new UserOnlineDTO();

        if (user.getDepartmentId() != null) {
            DepartmentDTO departmentDTO = this.getDepartmentDTO(user.getDepartmentId());
            userOnlineDTO.setDepartment(departmentDTO);
        }

        if (user.getPositionId() != null) {
            PositionDTO positionDTO = this.getPositionDTO(user.getPositionId());
            userOnlineDTO.setPosition(positionDTO);
        }

        if (user.getTenantId() != null) {
            TenantDTO tenantDTO = this.getTenantDTO(user.getTenantId());
            userOnlineDTO.setTenant(tenantDTO);
        }

        if (user.getCompanyId() != null) {
            CompanyDTO companyDTO = this.getCompanyDTO(user.getCompanyId());
            userOnlineDTO.setCompany(companyDTO);
        }

        if (user.getOrgId() != null) {
            OrganizationDTO organizationDTO = this.getOrganizationDTO(user.getOrgId());
            userOnlineDTO.setOrganization(organizationDTO);
        }

        HttpServletRequest request = ServletUtils.getRequest();
        String ip = HttpUtils.getIpAddress(request);
        String os = HttpUtils.getOsName(request);
        String browser = HttpUtils.getBrowserName(request) + " " + HttpUtils.getBrowserVersion(request);

        userOnlineDTO.setIpaddr(ip);
        userOnlineDTO.setLoginTime(this.getLoginTime());
        userOnlineDTO.setBrowser(browser);
        userOnlineDTO.setOs(os);
        userOnlineDTO.setName(user.getName());
        userOnlineDTO.setCode(user.getCode());
        userOnlineDTO.setId(user.getId());
        redisTemplate.opsForValue().set(USER_LOGING_KEY + user.getId(), userOnlineDTO);
    }

    private DepartmentDTO getDepartmentDTO(Long departmentId) {
        Department department = departmentMapper.selectByPrimaryKey(departmentId);
        return BeanUtil.copy(department, DepartmentDTO.class);
    }

    private CompanyDTO getCompanyDTO(Long companyId) {
        Company company = companyMapper.selectByPrimaryKey(companyId);
        return BeanUtil.copy(company, CompanyDTO.class);
    }

    private PositionDTO getPositionDTO(Long positionId) {
        Position position = positionMapper.selectByPrimaryKey(positionId);
        return BeanUtil.copy(position, PositionDTO.class);
    }

    private TenantDTO getTenantDTO(Long tenantId) {
        Tenant tenant = tenantMapper.selectByPrimaryKey(tenantId);
        return BeanUtil.copy(tenant, TenantDTO.class);
    }

    private OrganizationDTO getOrganizationDTO(Long organizationId) {
        Organization organization = organizationMapper.selectByPrimaryKey(organizationId);
        return BeanUtil.copy(organization, OrganizationDTO.class);
    }

    private String getLoginTime() {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return dateTimeFormatter.format(now);
    }

    private Boolean selectOnlineByInfo(UserOnlineQuery userOnlineQuery, UserOnlineDTO userOnlineDTO) {
        // userOnlineDTO 不能为空  userOnlineQuery 为空查询所有
        if (!Objects.isNull(userOnlineDTO)) {
            // 根据code和 name进行查询 非空判断
            if (!StringUtils.isEmpty(userOnlineQuery.getCode()) && !StringUtils.isEmpty(userOnlineQuery.getName())) {
                // 是否包含
                if (StringUtils.contains(userOnlineDTO.getCode(), userOnlineQuery.getCode()) && StringUtils.contains(userOnlineDTO.getName(), userOnlineQuery.getName())) {
                    return true;
                }
                return false;
            }
            // 根据code查询 非空判断
            if (!StringUtils.isEmpty(userOnlineQuery.getCode())) {
                // 是否包含
                if (StringUtils.contains(userOnlineDTO.getCode(), userOnlineQuery.getCode())) {
                    return true;
                }
                return false;
            }
            // 更具name查询 非空判断
            if (!StringUtils.isEmpty(userOnlineQuery.getName())) {
                // 是否包含
                if (StringUtils.contains(userOnlineDTO.getName(), userOnlineQuery.getName())) {
                    return true;
                }
                return false;
            }
            // userOnlineQuery 为空的话 直接查询所有用户
            return true;
        }
        return false;
    }
}
